package com.mk.cloud.pt.controller.app;

import act.Act;
import act.apidoc.Description;
import act.controller.Controller;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.config.WxMaInMemoryConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mk.cloud.common.config.AppConfig;
import com.mk.cloud.common.domain.*;
import com.mk.cloud.common.enums.ErrorCode;
import com.mk.cloud.common.enums.GlobalValues;
import com.mk.cloud.common.exception.UserException;
import com.mk.cloud.common.interceptor.ITransacte;
import com.mk.cloud.common.interceptor.header.HeaderService;
import com.mk.cloud.common.interceptor.header.IHLogin;
import com.mk.cloud.common.util.*;
import com.mk.cloud.pt.service.app.PCompanyService;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.osgl.http.H;
import org.osgl.mvc.annotation.GetAction;
import org.osgl.mvc.annotation.PostAction;
import org.osgl.mvc.annotation.With;
import org.osgl.util.S;

import javax.inject.Inject;
import java.math.BigDecimal;
import java.util.*;

@Controller("app/puser")
public class PUserController extends HeaderService {

    @Inject
    private PUser.Mapper pUserMapper;

    @Inject
    private PScheme.Mapper pSchemeMapper;

    @Inject
    private PSchemeCode.Mapper pSchemeCodeMapper;

    @Inject
    private PCompanyService pCompanyService;

    @Inject
    private PCoconfig.Mapper pCocofigMapper;

    @Inject
    private WxMaServiceImpl wxMaServiceImpl;

    private static Set useridSet;

    /**
     * 登陆接口
     */
    private String login(String code,PCompany company) {
        if (S.isBlank(code)) {
            return "empty jscode";
        }
        try {
            WxMaInMemoryConfig config = new WxMaInMemoryConfig();
            config.setAppid(company.getAppid());
            config.setSecret(company.getAppsecret());
            wxMaServiceImpl.setWxMaConfig(config);
            WxMaJscode2SessionResult session = this.wxMaServiceImpl.getUserService().getSessionInfo(code);
            return JSON.toJSONString(session);
        } catch (WxErrorException e) {
            return e.toString();
        }
    }

    private synchronized String getFuserid(){
        if(useridSet==null){
            List<String> ids = pUserMapper.selectAllFuserids();
            useridSet = new HashSet(ids);
        }
        String fuserid = VerifyCodeUtils.generateVerifyCode(6);
        if(!useridSet.add(fuserid)){
            return this.getFuserid();
        }
        return fuserid;
    }

    @Description("微信小程序第一个接口,通过openid来确认登录人的身份")
    @With(ITransacte.class)
    public PUser openidLogin(
         @Description("小程序的唯一标识") String openid,
         @Description("小程序所属企业") String coid,
         @Description("小程序所属企业") JSONObject userinfo
    ){
        PUser pUserCash = Act.cache().get(openid);//根据openid缓存插入的数据

        PUser pUser = new PUser();
        pUser.setCoid(coid);
        pUser.setOpenid(openid);
//        pUser.setPustate("1");
//        pUser.setPlevel(GlobalValues.PLEVEL_0.value());
        PUser user = pUserMapper.templateOne(pUser);
        if(user==null||S.isBlank(user.getNickname())){
            pUser.setNickname(userinfo.getString("nickName"));
            pUser.setUserface(userinfo.getString("avatarUrl"));
            if(user==null){
                if(pUserCash!=null){
                    return pUserCash;
                }
                pUser.setFuserid(this.getFuserid());
                pUser.setWalletamount(BigDecimal.ZERO);
                pUser.setLockamount(BigDecimal.ZERO);
                pUser.setTotamount(BigDecimal.ZERO);
                pUser.setCreatetime(DateUtils.getTimeNow());
                Act.cache().put(openid,pUser, 5*60);//根据openid缓存插入的数据,缓存5分钟
                pUserMapper.insertTemplate(pUser);
                user = pUser;
            }else{
                pUser.setFuserid(user.getFuserid());
                pUserMapper.updateTemplateById(pUser);
                user.setNickname(userinfo.getString("nickName"));
                user.setUserface(userinfo.getString("avatarUrl"));
            }
        }
        return user;
    }

    @Description("微信小程序第一个接口,通过openid来确认登录人的身份")
    @PostAction("wechatlogin.json")
    @With(ITransacte.class)
    public String wechatLogin(
            H.Session session,
            @Description("小程序的标识") String appid,
            @Description("小程序的换取凭证") String code,
            @Description("小程序获取的公开信息") JSONObject userinfo

    ){
        try{
            PCompany pCompany = pCompanyService.getCompanyByAppid(appid);
            String logininfostr = login(code,pCompany);
            JSONObject logininfo = JSON.parseObject(logininfostr);
            PUser user = this.openidLogin(logininfo.getString("openid"),pCompany.getCoid(),userinfo);
            JSONObject json = new JSONObject();
            Act.cache().put(logininfo.getString("sessionKey"),user,AppConfig.cache.ttl.get());
            user.setOpenid(null);
            json.put("userInfo",user);
//            json.put("pCompany",pCompany);
            if(pCompany!=null){
                PCompany clone = (PCompany) BeanUtils.cloneBean(pCompany);
                if(pCompany.getPCoconfig()!=null){
                    PCoconfig coconfig = new PCoconfig();
                    coconfig.setBegintime(pCompany.getPCoconfig().getBegintime());
                    coconfig.setEndtime(pCompany.getPCoconfig().getEndtime());
                    clone.setPCoconfig(coconfig);
                }
                json.put("pCompany",clone);
            }
            json.put("token",logininfo.getString("sessionKey"));
            return ResUtils.OK(json);
        }catch (Exception e){
            throw new UserException("发生未知错误");
        }
    }

    @Description("微信小程序第一个接口,通过openid来确认登录人的身份")
    @GetAction("checkSession.json")
    @With({IHLogin.class,ITransacte.class})
    public String checkSession(
    ){
        return ResUtils.OK(me);
    }

    @Description("校验方案编码")
    @With(IHLogin.class)
    @PostAction("volidatecode.json")
    public String volidate(String code,String timestamp,String pscode,BigDecimal planamount){
//        checkImgCode(code,timestamp);
        //需要替换新方案
        if(S.isBlank(pscode)){
            throw new UserException("方案编码不能为空");
        }
        pscode = pscode.toUpperCase();
//        String sid = pSchemeMapper.getByCodeAndAmount(pscode,planamount);
//        if(S.isBlank(sid)){
//            throw new UserException("方案编码无效或与金额不一致");
//        }
        PUser pUser = new PUser();
        pUser.setPscode(pscode);
        long count = pUserMapper.templateCount(pUser);
        if(count>0){
            throw new UserException("该方案已经使用过了");
        }
        PSchemeCode pSchemeCode = new PSchemeCode();
        pSchemeCode.setPscode(pscode);
        pSchemeCode.setCoid(me.getCoid());
        PSchemeCode schemeCode = pSchemeCodeMapper.templateOne(pSchemeCode);
        if(schemeCode==null){
            throw new UserException("该方案不存在");
        }

        PScheme scheme = pSchemeMapper.single(schemeCode.getSid());
        if(S.neq(scheme.getPublishstatus(),GlobalValues.PUBLISH_STATUS_1.value())){
            throw new UserException("该方案已失效");
        }
        planamount = scheme.getSamount();
        if(me.getPlanamount()!=null&&planamount.compareTo(me.getPlanamount())<=0){
            throw new UserException("方案只能升级");
        }
        return ResUtils.OK();
    }

    @Description("补充合伙人信息/或用户信息/合伙人注册")
    @PostAction("update.json")
    @With({IHLogin.class,ITransacte.class})
    public String updatePUser(
            @Description("合伙人信息") PUser user,
            @Description("图形验证码") String code,
            @Description("时间戳") String timestamp
    ){
        user.setPfuserid(null);
//        checkImgCode(code,timestamp);
        //需要替换新方案
        if(S.isBlank(user.getPscode())){
            throw new UserException("方案编码不能为空");
        }
        user.setPscode(user.getPscode().toUpperCase());
//        String sid = pSchemeMapper.getByCodeAndAmount(user.getPscode(),user.getPlanamount());
//        if(S.isBlank(sid)){
//            throw new UserException("方案编码无效或与金额不一致");
//        }
        PUser pUser = new PUser();
        pUser.setPscode(user.getPscode());
        long count = pUserMapper.templateCount(pUser);
        if(count>0){
            throw new UserException("该方案已经使用过了");
        }
        PSchemeCode pSchemeCode = new PSchemeCode();
        pSchemeCode.setPscode(user.getPscode());
        pSchemeCode.setCoid(me.getCoid());
        PSchemeCode schemeCode = pSchemeCodeMapper.templateOne(pSchemeCode);
        if(schemeCode==null){
            throw new UserException("该方案不存在");
        }

        PScheme scheme = pSchemeMapper.single(schemeCode.getSid());
        if(S.neq(scheme.getPublishstatus(),GlobalValues.PUBLISH_STATUS_1.value())){
            throw new UserException("该方案已失效");
        }
        user.setPlanamount(scheme.getSamount());

        if(me.getPlanamount()!=null&&user.getPlanamount().compareTo(me.getPlanamount())<=0){
            throw new UserException("方案只能升级");
        }
        if(S.isNotBlank(me.getPscode())&&!S.eq(user.getPscode(),me.getPscode())){
            PUser userOld = pUserMapper.single(me.getFuserid());
            userOld.setFuserid(S2.UUID());
            userOld.setPustate("0");//0覆盖,1正常
            pUserMapper.insertTemplate(userOld);
        }
        user.setFuserid(me.getFuserid());
        user.setPlevel(GlobalValues.PLEVEL_0.value());
        user.setCreatetime(DateUtils.getTimeNow());
        pUserMapper.updateTemplateById(user);
        PUser newuser = refreshUser();
        return ResUtils.OK(newuser);
    }

    /**
     * 刷新缓存中的用户信息
     * @return
     */
    @NotNull
    private PUser refreshUser() {
        PUser newuser = pUserMapper.selectPUserByid(me.getFuserid());
        newuser.setAlipaypwd(null);
        Act.cache().put(getToken(),newuser, AppConfig.cache.ttl.get());
        newuser.setOpenid(null);
        return newuser;
    }

    /**
     * 校验图形验证码
     * @param code
     */
    private void checkImgCode(@Description("图形验证码") String code,
                              @Description("时间戳") String timestamp) {
        //region 图形验证码开始验证 TODO 图形验证码 需要更新一下机制
        UserException.throwIf(StringUtils.isBlank(code), ErrorCode.E201014);
        String cachedCodeImg = Act.cache().get(timestamp);
        UserException.throwIf(!StringUtils.equalsIgnoreCase(cachedCodeImg,code),ErrorCode.E201009);
        //endregion
    }

    @Description("补充合伙人信息/或用户信息")
    @PostAction("updateAlipay.json")
    @With({IHLogin.class,ITransacte.class})
    public String updatePUserAlipay(
            @Description("合伙人信息") PUser user,
            @Description("合伙人原支付密码") String alipaypwdold,
            @Description("合伙人支付密码") String alipaypwd,
            @Description("图形验证码") String code,
            @Description("时间戳") String timestamp
    ){
        checkImgCode(code,timestamp);

        PUser oldUser = pUserMapper.single(me.getFuserid());
//        PUser pUser = new PUser();
//        pUser.setAlipaypwd(EncyUtils.MD5(alipaypwdold));
//        pUser.setFuserid(me.getFuserid());

        if(oldUser==null||(S.isNotBlank(oldUser.getAlipaypwd())&&S.neq(oldUser.getAlipaypwd(),EncyUtils.MD5(alipaypwdold)))){
            throw new UserException("原密码错误,不能修改");
        }
        //endregion
        user.setAlipaypwd(null);
        if(S.isNotBlank(alipaypwd)){
            user.setAlipaypwd(EncyUtils.MD5(alipaypwd));
        }
        user.setFuserid(me.getFuserid());
        pUserMapper.updateTemplateById(user);
        PUser newuser = refreshUser();
        return ResUtils.OK(newuser);
    }

    @Description("缓存分享人")
    @PostAction("shareman.json")
    @With({IHLogin.class,ITransacte.class})
    public String shareman(
            @Description("分享人id") String pfuserid2
    ){
        if(S.isBlank(pfuserid2)||S.eq(pfuserid2,me.getFuserid())){
            return ResUtils.OK(me);
        }
        PUser shareUser = pUserMapper.single(pfuserid2);
        if(shareUser==null||
                (S.neq(shareUser.getPlevel(),GlobalValues.PLEVEL_1.value())&&
                        S.neq(shareUser.getPlevel(),GlobalValues.PLEVEL_2.value()))
                ){
            return ResUtils.OK(me);
        }

        PUser user1 = pUserMapper.single(me.getFuserid());
        if(S.isBlank(user1.getPfuserid2())){//如果用户没有相应的推广人信息,则将第一个推广人存入数据库
            PUser user = new PUser();
            user.setFuserid(me.getFuserid());
            user.setPfuserid2(pfuserid2);
            pUserMapper.updateTemplateById(user);//将第一个分享人存到数据库pfuserid2字段中
            me.setPfuserid2(pfuserid2);
        }
        Act.cache().put(me.getFuserid(),pfuserid2, AppConfig.cache.ttl.get());
        Act.cache().put(getToken(),me, AppConfig.cache.ttl.get());
        return ResUtils.OK(me);
    }

    @Description("查询当前登录人信息")
    @GetAction("get.json")
    @With({IHLogin.class,ITransacte.class})
    public String getPUser(){
        PUser newuser = refreshUser();
        return ResUtils.OK(newuser);
    }

    @Description("查询公众号企业信息")
    @GetAction("configtime.json")
    public String pCoconfigTime(String appid){
        PCompany pCompany = pCompanyService.getCompanyByAppid(appid);
        Map<String,Object> map = new HashMap<>();
        map.put("now",DateUtils.getTimeNow());
        if(pCompany!=null){
            PCoconfig pCoconfig = pCocofigMapper.single(pCompany.getCoid());
            PCoconfig coconfig = new PCoconfig();
            if(pCoconfig!=null){
                coconfig.setBegintime(pCoconfig.getBegintime());
                coconfig.setEndtime(pCoconfig.getEndtime());
            }
            map.put("pCoconfig",coconfig);
            return ResUtils.OK(map);
        }
        return ResUtils.OK(map);
    }


}
